package se.simbio.encryption.slice;

import ohos.aafwk.content.Operation;
import ohos.agp.components.Button;
import ohos.agp.components.Component;
import ohos.agp.components.Text;
import ohos.agp.components.TextField;
import ohos.agp.window.dialog.ToastDialog;
import ohos.app.dispatcher.TaskDispatcher;
import ohos.hiviewdfx.HiLog;
import ohos.hiviewdfx.HiLogLabel;
import se.simbio.encryption.Encryption;
import se.simbio.encryption.ResourceTable;
import ohos.aafwk.ability.AbilitySlice;
import ohos.aafwk.content.Intent;
import third.part.android.util.Base64;

import java.security.NoSuchAlgorithmException;

public class MainAbilitySlice extends AbilitySlice implements Component.ClickedListener {

    private static final HiLogLabel TAG = new HiLogLabel(0, 0, "Encryption");
    Encryption encryption = Encryption.getDefault("SomeKey", "SomeSalt", new byte[16]);

    private Text mTextView;
    private Button mUsageNormal;
    private Button mUsageCustomized;
    private Button mUsageAsync;

    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        super.setUIContent(ResourceTable.Layout_ability_example);
        mTextView = (Text) findComponentById(ResourceTable.Id_log_textView);
        mUsageNormal = (Button) findComponentById(ResourceTable.Id_usage_normal);
        mUsageNormal.setClickedListener(this);
        mUsageCustomized = (Button)findComponentById(ResourceTable.Id_usage_customized);
        mUsageCustomized.setClickedListener(this);
        mUsageAsync = (Button) findComponentById(ResourceTable.Id_usage_async);
        mUsageAsync.setClickedListener(this);
    }

    private void log(final String message) {
        HiLog.debug(TAG, message, null);
        TaskDispatcher taskDispatcher = getContext().getUITaskDispatcher();
        taskDispatcher.asyncDispatch(new Runnable() {
            @Override
            public void run() {
                mTextView.append(message + "\n");
            }
        });
    }

    @Override
    public void onActive() {
        super.onActive();
    }

    @Override
    public void onForeground(Intent intent) {
        super.onForeground(intent);
    }

    @Override
    public void onClick(Component component) {
        switch (component.getId()){
            case ResourceTable.Id_usage_normal:
                log("---- Normal Usage ---------------------------------------------------");
                String secretText = "This is a text to be encrypt, it can be any string that you want";
                // the method encryptOrNull will encrypt your text and if some error occurs will return null
                // if you want handle the errors you can call the encrypt method directly
                String encrypted = encryption.encryptOrNull(secretText);
                // just printing to see the text and the encrypted string
                log("This is our secret text: " + secretText);
                log("And this is our encrypted text: " + encrypted);
                // now you can send the encrypted text by network or save in disk securely or do wherever
                // that you want, but remember encrypt is not all, we need decrypt too, so lets go do it
                String decrypted = encryption.decryptOrNull(encrypted);
                // the decrypted text should be equals the encrypted
                log("And finally this is our decrypted text: " + decrypted);
                break;
            case ResourceTable.Id_usage_customized:
                log("---- Customized Usage -----------------------------------------------");
                // if you want to change Encryption behavior, maybe to reduce the Iteration Count to get a
                // better performance or also change the Algorithm to a customizable one. You can do this
                // things using your own Encryption.Builder, you can get the default e change few things
                try {
                    encryption = Encryption.Builder.getDefaultBuilder("MyKey", "MySalt", new byte[16])
                            .setIterationCount(1) // use 1 instead the default of 65536
                            .build();
                } catch (NoSuchAlgorithmException e) {
                    log("Something wrong: " + e);
                }
                try {
                    encryption = new Encryption.Builder()
                            .setKeyLength(128)
                            .setKeyAlgorithm("AES")
                            .setCharsetName("UTF8")
                            .setIterationCount(65536)
                            .setKey("mor€Z€cr€tKYss")
                            .setDigestAlgorithm("SHA1")
                            .setSalt("A beautiful salt")
                            .setBase64Mode(Base64.DEFAULT)
                            .setAlgorithm("AES/CBC/PKCS5Padding")
                            .setSecureRandomAlgorithm("SHA1PRNG")
                            .setSecretKeyType("PBKDF2WithHmacSHA1")
                            .setIv(new byte[] { 29, 88, -79, -101, -108, -38, -126, 90, 52, 101, -35, 114, 12, -48, -66, -30 })
                            .build();
                } catch (NoSuchAlgorithmException e) {
                    log("Something wrong: " + e);
                }
                log("Our encryption instance, can't be null: " + encryption);
                break;
            case ResourceTable.Id_usage_async:
                log("---- Async Usage ----------------------------------------------------");
                // the encryption algorithm can take some time and if you cannot lock the thread and wait
                // maybe use an async approach is a good idea, so you can do this like below:
                // this method will create a thread and works there, the callback is called when the job is done
                encryption.encryptAsync("This is the text to be encrypt", new Encryption.Callback() {
                    @Override
                    public void onSuccess(String encrypted) {
                        // if no errors occurs you will get your encrypted text here
                        log("My encrypted text: " + encrypted);
                    }

                    @Override
                    public void onError(Exception e) {
                        // if an error occurs you will get the exception here
                        log("Oh no! an error has occurred: " + e);
                    }
                });
                log("A print from original thread");
                break;
            default:
                break;
        }
    }
}
